package ar.com.sectorwine.controllers;

import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.Validator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;

import ar.com.sectorwine.dto.EmpresaDTO;
import ar.com.sectorwine.dto.EmpresasDTOMapper;
import ar.com.sectorwine.dto.UsuarioABMDTO;
import ar.com.sectorwine.dto.UsuarioABMDTOMapper;
import ar.com.sectorwine.entities.Empresa;
import ar.com.sectorwine.entities.Publicacion;
import ar.com.sectorwine.entities.Users;
import ar.com.sectorwine.services.EmpresasService;
import ar.com.sectorwine.services.PublicacionesService;
import ar.com.sectorwine.services.UsuarioService;
import excepciones.ExcepcionGeneral;

/**
 * Handles requests for the application home page.
 */
/**
 * @author Ismael
 *
 */
@Controller
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class EmpresasController {

	@Autowired
	private EmpresasService empresasService;
	@Autowired
	private UsuarioService usuarioService;
	@Autowired
	private EmpresasDTOMapper empresasDTOMapper;
	@Autowired
	private PublicacionesService publicacionesService;
	@Autowired
	private UsuarioABMDTOMapper usuarioABMDTOMapper;

	private static final Logger logger = LoggerFactory
			.getLogger(EmpresasController.class);
	@Autowired
	private Validator validator;

	
	/**
  	  *
	  * @param locale (Parametro relacionado con Spring MVC).
	  * @param model (Parametro relacionado con Spring MVC).
	  * @param principal (Parametro relacionado con Spring MVC).
	  * 
	  * @return String ("empresas/empresas_alta")
	  **/
	@RequestMapping(value = "empresas_alta", method = RequestMethod.GET)
	public String registro(Locale locale, Model model, Principal principal) {

		logger.info("Welcome home! the client locale is " + locale.toString());
		model.addAttribute("empresa", new EmpresaDTO());
		List<UsuarioABMDTO> usuarios = ChatController.obtenercontactos(
				principal.getName(), usuarioService, usuarioABMDTOMapper);
		model.addAttribute("usuarios", usuarios);

		return "empresas/empresas_alta";
	}

	/**
	  *
	  * @param empresaDTO EmpresaDTO
	  * @param BindingResult (Parametro relacionado con Spring MVC).
	  * @param SessionStatus (Parametro relacionado con Spring MVC).
	  * @param Principal (Parametro relacionado con Spring MVC).
	  * 
	  * @return ModelAndView
	  **/
	@RequestMapping(value = "/empresas_alta", method = RequestMethod.POST)
	public ModelAndView create(
			@Valid @ModelAttribute("empresa") EmpresaDTO empresaDTO,
			BindingResult result, SessionStatus status, Principal principal) {
		logger.info("controller");

		List<UsuarioABMDTO> usuarios = ChatController.obtenercontactos(
				principal.getName(), usuarioService, usuarioABMDTOMapper);

		try {
			Empresa empresa = empresasDTOMapper
					.obtenerObjetoDelDominioDesdeDTO(empresaDTO);

			Users usuarioActual = usuarioService
					.getUsuario(principal.getName());

			Set<ConstraintViolation<EmpresaDTO>> failures = validator
					.validate(empresaDTO);

			if (failures.size() == 0) {
				if (empresa != null) {
					empresasService.crearEmpresa(empresa, usuarioActual);
					status.setComplete();
					ModelAndView mav = new ModelAndView(
							"empresas/empresas_perfil");
					mav.addObject("mensajeCabecera",
							"La empresa '" + empresa.getRazonSocial()
									+ "' se creo de manera existosa!");
					mav.addObject("empresa", empresa);
					mav.addObject("usuarios", usuarios);
					return mav;
				} else {
					ModelAndView mav = new ModelAndView(
							"empresas/empresas_alta");
					mav.addObject("empresa", empresaDTO);
					mav.addObject("usuarios", usuarios);
					return mav;
				}
			} else {
				ModelAndView mav = new ModelAndView("empresas/empresas_alta");
				mav.addObject("empresa", empresaDTO);
				for (Object o : failures) {
					logger.info(o.toString());
				}
				mav.addObject("usuarios", usuarios);
				return mav;
			}
		} catch (ExcepcionGeneral e1) {

			ModelAndView mav = new ModelAndView("empresas/empresas_alta");
			mav.addObject("empresa", empresaDTO);
			if(e1.getAtributo() != null && !e1.getAtributo().trim().isEmpty()){
				if(e1.getMensajeCorto() != null && !e1.getMensajeCorto().trim().isEmpty()){
					result.rejectValue(e1.getAtributo(), "messageCode",
							e1.getMensajeCorto());
				}
			}
	
			
			mav.addObject("mensajeCabecera", e1.getMessage());
			
			mav.addObject("usuarios", usuarios);
			return mav;
		} catch (Exception e2) {

			ModelAndView mav = new ModelAndView("empresas/empresas_alta");
			mav.addObject("empresa", empresaDTO);
			// mav.addObject("");
			mav.addObject("usuarios", usuarios);
			return mav;
		}
	}

	/**
	  *
	  * @param Locale (Parametro relacionado con Spring MVC).
	  * @param Model (Parametro relacionado con Spring MVC).
	  * @param Principal (Parametro relacionado con Spring MVC).
	  * 
	  * @return ModelAndView
	  **/
	@RequestMapping(value = "empresas_miempresa", method = RequestMethod.GET)
	public ModelAndView miEmpresa(Locale locale, Model model,
			Principal principal) {

		Users usuarioActual = usuarioService.getUsuario(principal.getName());

		if (!(usuarioActual.getPerfilUsuario().getEmpresas().isEmpty())) {
			ModelAndView mav = new ModelAndView("empresas/empresas_miempresa");
			mav.addObject("mis_empresas", usuarioActual.getPerfilUsuario()
					.getEmpresas());
			return mav;
		} else {
			ModelAndView mav = new ModelAndView("empresas/empresas_alta");
			mav.addObject("empresa", new EmpresaDTO());
			mav.addObject("mensajeCabecera",
					"Aun no tienes una empresa creada. Crea un perfil para ella!");
			logger.info("El usuario " + usuarioActual.getUsername()
					+ " no tiene empresa creada.");
			return mav;
		}

	}

	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "empresas_listar", method = RequestMethod.GET)
	public ModelAndView listar(Locale locale, Model model, Principal principal) {

		List<Users> usuarios = usuarioService.getListaUsuarios();
		List<UsuarioABMDTO> contactos = ChatController.obtenercontactos(
				principal.getName(), usuarioService, usuarioABMDTOMapper);
		if (!usuarios.isEmpty()) {
			List<Empresa> empresas = new ArrayList<Empresa>();
			for (int i = 0; i < usuarios.size(); i++) {
				if (!usuarios.get(i).getPerfilUsuario().getEmpresas().isEmpty()) {
					for (int j = 0; j < usuarios.get(i).getPerfilUsuario()
							.getEmpresas().size(); j++) {
						empresas.add(usuarios.get(i).getPerfilUsuario()
								.getEmpresas().get(j));
					}
				}
			}
			ModelAndView mav = new ModelAndView("empresas/empresas_listar");
			mav.addObject("empresasList", empresas);
			mav.addObject("usuarios", contactos);
			mav.addObject("tipoListado", true);
			return mav;
		} else {
			ModelAndView mav = new ModelAndView("home");
			mav.addObject("mensajeCabecera", "No hay empresas registradas");
			logger.info("No existen empresas registradas");
			mav.addObject("usuarios", contactos);
			return mav;
		}
	}



	@RequestMapping(value = "listar_siguiendo", method = RequestMethod.GET)
	public ModelAndView listarSiguiendo(Locale locale, Model model,
			Principal principal) {

		Users usuarioActual = usuarioService.getUsuario(principal.getName());
		List<UsuarioABMDTO> contactos = ChatController.obtenercontactos(
				principal.getName(), usuarioService, usuarioABMDTOMapper);
		
		List<Empresa> empresas = new ArrayList<Empresa>();
	
		for(Long idEmpresaSeguida: usuarioActual.getPerfilUsuario().getEmpresasSeguidas()) {
			
			empresas.add(empresasService.getEmpresa(idEmpresaSeguida.toString()));
				
		}
		ModelAndView mav = new ModelAndView("seguir/seguidores_listar");
		mav.addObject("empresasList", empresas);
		mav.addObject("titulo", "Siguiendo");
		mav.addObject("usuarios", contactos);
		return mav;
	}

	@RequestMapping(value = "empresas_perfil", method = RequestMethod.GET)
	public ModelAndView verPerfil(Locale locale, Principal principal,
			Model model, @RequestParam String id) {
		ModelAndView mav = new ModelAndView("empresas/empresas_perfil");
		Empresa empresa = empresasService.getEmpresa(id);
		mav.addObject("empresa", empresa);
		List<Publicacion> publicaciones = new ArrayList<Publicacion>();
		publicaciones = (publicacionesService.obtenerPublicaciones(empresa));

		mav.addObject("publicaciones", publicaciones);
		List<UsuarioABMDTO> usuarios = ChatController.obtenercontactos(
				principal.getName(), usuarioService, usuarioABMDTOMapper);
		mav.addObject("usuarios", usuarios);

		Users usuarioActual = usuarioService.getUsuario(principal.getName());

		if (usuarioActual.getPerfilUsuario().getEmpresas() != null) {
			mav.addObject("empresaPropia", usuarioActual.getPerfilUsuario()
					.getEmpresas().contains(empresa));
		} else {
			mav.addObject("empresaPropia", false);
		}

		if (usuarioActual.getPerfilUsuario().getEmpresasSeguidas() != null) {
			mav.addObject("siguiendo", usuarioActual.getPerfilUsuario()
					.getEmpresasSeguidas().contains(empresa.getId()));
		} else {
			mav.addObject("siguiendo", false);
		}
		return mav;
	}
	
	@RequestMapping(value = "/seguir_empresa", method = RequestMethod.GET)
	public ModelAndView seguirEmpresa(Locale locale, Model model,
			@RequestParam("idEmpresa") String idEmpresa, Principal principal) {

		logger.info("controller");

		Empresa empresa = empresasService.getEmpresa(idEmpresa);

		Users usuarioActual = usuarioService.getUsuario(principal.getName());

		if (empresa != null) {

			empresasService.seguirEmpresa(usuarioActual, empresa);

		}
		return verPerfil(locale, principal, model, idEmpresa);
	}

	@RequestMapping(value = "/no_seguir_empresa", method = RequestMethod.GET)
	public ModelAndView dejarDeSeguirEmpresa(Locale locale, Model model,
			@RequestParam("idEmpresa") String idEmpresa, Principal principal) {

		logger.info("controller");

		Empresa empresa = empresasService.getEmpresa(idEmpresa);

		Users usuarioActual = usuarioService.getUsuario(principal.getName());

		if (empresa != null) {

			empresasService.dejarDeSeguirEmpresa(usuarioActual, empresa);

		}

		return verPerfil(locale, principal, model, idEmpresa);
	}
}